﻿using System;
using System.Web.Mvc;
using AutoMapper;
using Tools.Common.Reflection;
using Web.App.Infrastructure.Localization.Contract;
using Webshop20.Application;
using Webshop20.Application.DataTransferObjects;
using Webshop20.Application.Operations.Messages;
using Webshop20.Application.Operations.Services;
using Webshop20.Application.Queries.Messages;
using Webshop20.Application.Queries.Services;
using Webshop20.Presentation;

namespace Webshop20.Interface.MVC.Controllers
{
    /// <summary>
    /// User enters his data. If they are correct, a new
    /// user object will be created and persistet.
    /// If he was called by the login use case the user
    /// will be redirected to the login page otherwise
    /// to the startpage. A message about the successful
    /// registration will be shown. If the data are not correct 
    /// the user will be redirected to the register page 
    /// and the errors will be shown.
    /// </summary>
    public class RegistrationController : ControllerBase
    {
        private readonly IInitializeNewRegistrationService initializeNewRegistrationService;
        private readonly IUpdateTransientNewRegistrationDataService updateAccountInProgressService;
        private readonly ISaveNewRegistrationService  saveNewRegistrationService;
        private readonly IGetNewRegistrationDataService getNewRegistrationDataService;
        private readonly IGetAccountValidationInformationService getAccountValidationInformationService;
        private readonly IGetControllQuestionsService getControllQuestionsService;
        private readonly IGetCustomerValidationInformationService getCustomerValidationInformationService;
        private readonly IPresentationModelFactory<RegistrationForm> presentationModelFactory;
        private ILocalisationService localisationService;
        
        public RegistrationController(

                                        ILocalisationService localisationService,
                                        IUpdateTransientNewRegistrationDataService updateAccountInProgressService,
                                        ISaveNewRegistrationService saveNewRegistrationService,
                                        IGetNewRegistrationDataService getNewRegistrationDataService,
                                        IGetCustomerValidationInformationService getCustomerValidationInformationService, 
                                        IGetAccountValidationInformationService getAccountValidationInformationService, 
                                        IPresentationModelFactory<RegistrationForm> presentationModelFactory, 
                                        IGetControllQuestionsService getControllQuestionsService, 
                                        IInitializeNewRegistrationService initializeNewRegistrationService) : base(localisationService)
        {
            this.getControllQuestionsService = getControllQuestionsService;
            this.initializeNewRegistrationService = initializeNewRegistrationService;
            this.presentationModelFactory = presentationModelFactory;
            this.getAccountValidationInformationService = getAccountValidationInformationService;
            this.getNewRegistrationDataService = getNewRegistrationDataService;
            this.saveNewRegistrationService = saveNewRegistrationService;
            this.updateAccountInProgressService = updateAccountInProgressService;
            this.getCustomerValidationInformationService = getCustomerValidationInformationService;
            this.localisationService = localisationService;
            
        }

        [AcceptVerbs("GET")]
        public ActionResult Index()
        {
            return Index(string.Empty, string.Empty);
        }

        [AcceptVerbs("GET")]
        public ActionResult Index(string accountInterimKey, string customerInterimKey)
        {
            var newRegistrationDTO = new NewRegistrationDTO();
            return IndexView(newRegistrationDTO, accountInterimKey, customerInterimKey);
        }

        private ActionResult IndexView(NewRegistrationDTO newRegistrationDTO, string accountInterimKey, string customerInterimKey)
        {
            var customerValidatorInformation = ((GetCustomerValidationInformationResponse) getCustomerValidationInformationService
                                                                                               .Handle(new GetCustomerValidationInformationRequest())).CustomerValidatorInformation;

            var accountValidatorInformation = ((GetAccountValidationInformationResponse) getAccountValidationInformationService
                                                                                             .Handle(new GetAccountValidationInformationRequest())).AccountValidatorInformation;
            var newRegistrationData =
                ((GetNewRegistrationDataResponse) getNewRegistrationDataService.Handle(new GetNewRegistrationDataRequest(accountInterimKey, customerInterimKey))).RegistrationData;

            var controllQuestions = ((GetControllQuestionResponse) getControllQuestionsService.Handle(new GetControllQuestionsRequest())).ControllQuestions;

            return View(
                presentationModelFactory
                    .Create(
                    newRegistrationData, 
                    customerValidatorInformation, 
                    accountValidatorInformation, 
                    controllQuestions, 
                    accountInterimKey, 
                    customerInterimKey
                    )
                );
        }

        [AcceptVerbs("POST")]
        [ActionName("Index")]
        public ActionResult UpdateAcountData(UpdateTransientNewRegistrationDataRequest request)
        {
            object overviewRouteData;

            if (request.AccountInterimsKey == null)
            {
                var initNewRegistrationResponse =
                    initializeNewRegistrationService.Handle(
                        new InitializeNewRegistrationRequest(request.FirstName, request.LastName, request.EMail,
                                                            request.Password, request.PasswordConfirm)) as InitializeNewRegistrationResponse;

                if (initNewRegistrationResponse.DomainMessage != null)
                {
                    AddErrorMessagesToViewDataModelState(initNewRegistrationResponse.DomainMessage);
                    return IndexView(
                            (NewRegistrationDTO)Mapper.Map(request, typeof(UpdateTransientNewRegistrationDataRequest), typeof(NewRegistrationDTO)), 
                            initNewRegistrationResponse.AccountInterimKey,
                            initNewRegistrationResponse.CustomerInterimKey
                        );
                }

                overviewRouteData =
                    new
                        {
                            accountInterimKey = initNewRegistrationResponse.AccountInterimKey,
                            customerInterimKey = initNewRegistrationResponse.CustomerInterimKey
                        };
            }
            else
            {
                var updateAccountInProgressResponse =
                 updateAccountInProgressService.Handle(request) as UpdateTransientAccountResponse;

                if (updateAccountInProgressResponse.DomainMessage != null)
                {
                    AddErrorMessagesToViewDataModelState(updateAccountInProgressResponse.DomainMessage);
                    return IndexView(
                                        (NewRegistrationDTO)Mapper.Map(request, typeof(UpdateTransientNewRegistrationDataRequest), typeof(NewRegistrationDTO)),
                                        request.AccountInterimsKey,
                                        request.CustomerInterimsKey
                                    );
                }

                overviewRouteData =
                    new
                        {
                            accountInterimKey = request.AccountInterimsKey,
                            customerInterimKey = request.CustomerInterimsKey
                        };
            }

            return RedirectToAction("Overview", overviewRouteData);
        }

        [AcceptVerbs("POST")]
        public ActionResult Overview(string accountInterimKey, string customerInterimKey)
        {
            var response = getNewRegistrationDataService.Handle(new GetNewRegistrationDataRequest(accountInterimKey, customerInterimKey)) as
                GetNewRegistrationDataResponse;

            return View(new RegistrationOverview(localisationService, accountInterimKey, customerInterimKey, response.RegistrationData));
        }

        [AcceptVerbs("POST")]
        public ActionResult FinishRegistration(string accountInterimKey, string customerInterimKey)
        {
            saveNewRegistrationService.Handle(new SaveNewRegistrationRequest(accountInterimKey, customerInterimKey));

            return RedirectToAction<RegistrationController>(controller=>controller.Success());
        }

        public ActionResult Success()
        {
            return View();
        }


    }
}
